#ifndef _TESTER_CONV2_CUH_
#define _TESTER_CONV2_CUH_

#include "cuda_conv2.cuh"

namespace cuda_matrix{
    namespace tester{
        template<typename MA, typename MM,typename MF>
        inline void test_conv2( MA ans, 
                                const MM mat, const MF filter,
                                MA d_ans, MM d_mat, MF d_filter,
                                double &cost_all, double &cost_cal,
                                void conv2_tt( MA ans, const MM mat, const MF ft )){
            clock_t start_t = clock();
            
            
            matcpy( d_filter, filter , cudaMemcpyHostToDevice );
            matcpy( d_mat   , mat    , cudaMemcpyHostToDevice );
            
            clock_t cal_start = clock();
            
            conv2_tt( d_ans, d_mat , d_filter );
            
            cudaThreadSynchronize();

            cost_cal += clock() - cal_start;
            
            matcpy( ans, d_ans, cudaMemcpyDeviceToHost );
            
            cost_all += clock() - start_t;            
        }


        template<int map_m,typename MA, typename MM,typename MF>
        inline void test_conv2_r_valid_A( MA ans, 
                                          const MM mat, const MF filter,
                                          MA d_ans, MM d_mat, MF d_filter,
                                          double &cost_all, double &cost_cal ){
            test_conv2<MA,MM,MF>( ans, mat, filter, d_ans, d_mat, d_filter, cost_all, cost_cal , conv2_r_valid_A<map_m,0> );
        }

        template<int map_m,typename MA, typename MM,typename MF>
        inline void test_conv2_r_valid_3DGrid( MA ans, 
                                               const MM mat, const MF filter,
                                               MA d_ans, MM d_mat, MF d_filter,
                                               double &cost_all, double &cost_cal ){
            test_conv2<MA,MM,MF>( ans, mat, filter, d_ans, d_mat, d_filter, cost_all, cost_cal , conv2_r_valid_3DGrid<map_m,0> );
        }
        
        template<int map_m,typename MA, typename MM, typename MF>
        inline void test_conv2_full_A(  MA ans, 
                                        const MM mat, const MF filter,
                                        MA d_ans, MM d_mat, MF d_filter,
                                        double &cost_all, double &cost_cal ){
            test_conv2<MA,MM,MF>( ans, mat, filter, d_ans, d_mat, d_filter, cost_all, cost_cal , conv2_full_A<map_m,0> );
        }

        template<int map_m,typename MA, typename MM, typename MF>
        inline void test_conv2_full_3DGrid(  MA ans, 
                                             const MM mat, const MF filter,
                                             MA d_ans, MM d_mat, MF d_filter,
                                             double &cost_all, double &cost_cal ){
            test_conv2<MA,MM,MF>( ans, mat, filter, d_ans, d_mat, d_filter, cost_all, cost_cal , conv2_full_3DGrid<map_m,0> );
        }

        template<int map_m,typename MA, typename MM, typename MF>
        inline void test_conv2_r_big_filter_B(  MA ans, 
                                              const MM mat, const MF filter,
                                              MA d_ans, MM d_mat, MF d_filter,
                                              double &cost_all, double &cost_cal ){
            test_conv2<MA,MM,MF>( ans, mat, filter, d_ans, d_mat, d_filter, cost_all, cost_cal , conv2_r_big_filter_B<map_m,0> );
        }
        
        template<int map_m,typename MA, typename MM, typename MF>
        inline void test_conv2_r_big_filter_C(  MA ans, 
                                                const MM mat, const MF filter,
                                                MA d_ans, MM d_mat, MF d_filter,
                                                double &cost_all, double &cost_cal ){
            test_conv2<MA,MM,MF>( ans, mat, filter, d_ans, d_mat, d_filter, cost_all, cost_cal , conv2_r_big_filter_C<map_m,0> );
        }

        template<int map_m,typename MA, typename MM, typename MF>
        inline void test_conv2_r_big_filter_C_Grid(  MA ans, 
                                                     const MM mat, const MF filter,
                                                     MA d_ans, MM d_mat, MF d_filter,
                                                     double &cost_all, double &cost_cal ){
            test_conv2<MA,MM,MF>( ans, mat, filter, d_ans, d_mat, d_filter, cost_all, cost_cal , conv2_r_big_filter_C_Grid<map_m,0> );
        }
    };    
};

#endif
